#include <iostream>
#include <memory>
//#include <H5Cpp.h>
#include <fstream>
#include "json.hpp"

#include <boost/process.hpp>
#include <boost/locale.hpp>
#include <boost/dll/shared_library.hpp>
#include <boost/dll/runtime_symbol_info.hpp>
#include <boost/filesystem.hpp>
#include <boost/exception/all.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/stacktrace.hpp>

// #include <aws/core/Aws.h>
// #include <aws/core/auth/AWSCredentialsProvider.h>
// #include <aws/s3/S3Client.h>
// #include <aws/s3/model/PutObjectRequest.h>
// #include <aws/s3/model/GetObjectRequest.h>

#include "gen-cpp/CallService.h"
#include <thrift/transport/TSocket.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TBufferTransports.h>

using namespace std;
using namespace nlohmann;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

int main(int argc, char* argv[]){
    try{
        int port = 9080, try_times = 3;
        shared_ptr<TSocket> socket(new TSocket("127.0.0.1",port));
        shared_ptr<TTransport> transport(new TBufferedTransport(socket));
        shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
        function<void()> defer([&]{
            if(transport->isOpen())
                transport->close();
        });
        CallServiceClient client(protocol);
        do{
            try{
                transport->open();
            }catch(...){
                if(try_times==3){
                    auto base_path = boost::dll::program_location().parent_path();
                    string command = (base_path/"caller_matlab_server ").string();
                    boost::process::child(command+to_string(port),boost::process::start_dir(
                        boost::filesystem::absolute(boost::filesystem::path("caller_matlab_server")).parent_path().string()),
                        boost::process::std_out.close()).detach();
                }
                this_thread::sleep_for(chrono::seconds(10));
            }
        }while(!transport->isOpen() && try_times-->0);

        if(argc>2){
            string ret_string,param = argv[2];//boost::algorithm::replace_all_copy(string(argv[2]),"\"","\\\"");
            client.Process(ret_string,argv[1],param);
            cout << ret_string;
        }else{
            cout<<"parameter not enough"<<endl;
        }
    }catch (boost::exception &e) {
        cout << boost::stacktrace::stacktrace() << endl;
        cout << boost::diagnostic_information(e) << endl;
    }
    return 0;
}